using System;
using System.Text;
using Echo.Context.UltiProNet.Contexts;
using Echo.Context.UltiProNet.PageObjects;
using Echo.Core.Common;
using Echo.Core.TestAbstraction.WebUITest.MbUnit;
using Echo.Models.UltimateSoftware.WebUITest.MbUnit;
using MbUnit.Framework;

namespace Echo.Automation.Compliance.BusinessRules.Taxes
{
    [TestFixture]
    [Header("Config")]
    [Config(".NET")]
    [Author("Daniel Pritchett")]
    [Category("Business Rules")]
    public class Ny006TaxContributionRate : MbUnitAutomatedTest
    {
        #region Properties

        private const string Coid = "C0014";
        private const string EndOfTime = "12/31/2099";
        private const string Under312500 = "Under $312,500 (0.00%)";
        private const string Between375And437 = "Over $375,000 but not over $437,500 (0.23%)";
        private const string Between312And375 = "Over $312,500 but not over $375,000 (0.11%)";
        private const string Over437500 = "Over $437,500 (0.34%)";
        private const string RetroErrorMessage = "The effective date entered is retroactive. To configure retroactive changes, " +
        "go to Company Tax Setup in the Backoffice (Company Tax Setup > State > Choose applicable tax code).";

        UltiPro UltiPro { get; set; }
        UltiProDatabaseContext Database;

        DateTime CurrentDate { get; set; }

        ITaxCodeContributionRateContext Page { get { return UltiPro.Pages.TaxCodeContributionRate; } }

        string CurrentYear { get { return CurrentDate.Year.ToString(); } }

        string PriorYear { get { return CurrentDate.AddYears(-1).Year.ToString(); } }

        string NextYear { get { return CurrentDate.AddYears(1).Year.ToString(); } }

        #endregion

        #region Setup/Teardown

        [FixtureSetUp]
        public void FixtureSetUp()
        {
            UltiPro = Launch<UltiPro>();
            Database = Init<UltiProDatabaseContext>();
            Database.Company = ConfigDatabase("ULTIPRO_CALENDAR");
            Database.Company.AddRollBack("taxcrate", string.Format("tcrtaxcode = 'NY006' and tcrcoid = '{0}'", Coid));
            Database.Macros.BusinessRules.DisableRetroCalcs();
        }

        [FixtureTearDown]
        public void FixtureTearDown()
        {
            UltiPro.Browser.Quit();
        }

        [SetUp]
        public void SetUp()
        {
            CurrentDate = DateTime.Now;
            var effectiveDate = string.Format("04/01/{0}", CurrentYear);
            Database.Macros.BusinessRules.SetupTaxCRateData(Coid, ".0034", effectiveDate, EndOfTime);
            UltiPro.Macros.BusinessRules.GoToTaxContribPage();
        }

        [TearDown]
        public void TearDown()
        {
            UltiPro.Macros.Logout.Of_UltiPro();
            Database.Company.RollBackDatabase();
        }

        #endregion

        [Test]
        public void ValidateDefaultValues()
        {
            Page.Click(page => page.UpdateContributionRateCheckbox);

            var validYears = GetValidYears();
            Page.HasOptions(page => page.NY006YearDropDown, validYears);
            ValidateAvailableQuarters();
            ValidateQuarterlyPayrollExpense();
        }

        #region Verify Ny006 Records On Grid

        [Test]
        public void ValidateSaveQuartelyTotalPayrollExpenseFirstQuarter()
        {
            SaveNy006Record(NextYear, "01/01", Between375And437);
            UltiPro.Macros.BusinessRules.NavigateToTaxContribPage("NY006");
            AssertRowsExist(
                new[] { "0.23 %", string.Format("01/01/{0}", NextYear), Between375And437 },
                new[] { "0.34 %", string.Format("04/01/{0}", CurrentYear), Over437500 });
        }

        [Test]
        public void ValidateSaveQuartelyTotalPayrollExpenseSecondQuarter()
        {
            SaveNy006Record(NextYear, "04/01", Under312500);
            UltiPro.Macros.BusinessRules.NavigateToTaxContribPage("NY006");
            AssertRowsExist(
                new[] { "0.00 %", string.Format("04/01/{0}", NextYear), Under312500 },
                new[] { "0.34 %", string.Format("04/01/{0}", CurrentYear), Over437500 });
        }

        [Test]
        public void ValidateSaveQuartelyTotalPayrollExpenseThirdQuarter()
        {
            SaveNy006Record(CurrentYear, "07/01", Over437500);
            UltiPro.Macros.BusinessRules.NavigateToTaxContribPage("NY006");
            AssertRowsExist(
                new[] { "0.34 %", string.Format("07/01/{0}", CurrentYear), Over437500 },
                new[] { "0.34 %", string.Format("04/01/{0}", CurrentYear), Over437500 });
        }

        [Test]
        public void ValidateSaveQuartelyTotalPayrollExpenseFourthQuarter()
        {
            SaveNy006Record(CurrentYear, "10/01", Between312And375);
            UltiPro.Macros.BusinessRules.NavigateToTaxContribPage("NY006");
            AssertRowsExist(
                new[] { "0.11 %", string.Format("10/01/{0}", CurrentYear), Between312And375 },
                new[] { "0.34 %", string.Format("04/01/{0}", CurrentYear), Over437500 });
        }

        #endregion

        #region Toolbar Button Tests

        [Test]
        public void TestReset()
        {
            Page.Click(page => page.UpdateContributionRateCheckbox);
            Page.Set(page => page.NY006YearDropDown, NextYear);
            Page.Set(page => page.NY006QuarterDropDown, "4", SelectOption.Text);
            Page.Set(page => page.NY006QuarterlyTotalPayrollExpenseDropDown, Over437500, SelectOption.Text);
            Page.ButtonBar.Click(bar => bar.Reset);

            Page.NotSelected(page => page.UpdateContributionRateCheckbox);
            Page.NotEnabled(page => page.NY006YearDropDown);
            Page.NotEnabled(page => page.NY006QuarterDropDown);
            Page.NotEnabled(page => page.NY006QuarterlyTotalPayrollExpenseDropDown);
        }

        [Test]
        public void TestCancel()
        {
            const string description = Between375And437;

            Page.Click(page => page.UpdateContributionRateCheckbox);
            Page.Set(page => page.NY006YearDropDown, CurrentYear);
            Page.Set(page => page.NY006QuarterDropDown, "2", SelectOption.Text);
            Page.Set(page => page.NY006QuarterlyTotalPayrollExpenseDropDown, description, SelectOption.Text);

            Page.ButtonBar.Click(bar => bar.Cancel);
            UltiPro.Alert.Accept();
            UltiPro.Macros.BusinessRules.NavigateToTaxContribPage("NY006");
            Page.NY006HistoryGrid.Row(grid => grid.Description, description).RowNotExists();
        }

        [Test]
        public void TestHelp()
        {
            Page.ButtonBar.Click(bar => bar.Help);
            UltiPro.Browser.SwitchToWindow("Online Help");
            UltiPro.Browser.Close();
            UltiPro.Browser.SwitchToMainWindow();
        }

        [Test]
        public void TestPrint()
        {
            Page.ButtonBar.Click(bar => bar.Print);
            UltiPro.Browser.SwitchToWindow("Print Preview");
            UltiPro.Pages.PrintPreview.Click(preview => preview.CloseButton);
            UltiPro.Browser.SwitchToMainWindow();
        }

        #endregion

        #region Verify Save To TaxCRate

        [Test]
        public void ValidateSaveQuartelyTotalPayrollExpenseFirstQuarterTaxCRate()
        {
            SaveNy006Record(NextYear, "01/01", Under312500);
            UltiPro.Macros.BusinessRules.NavigateToTaxContribPage("NY006");
            ValidateTaxCRate("Ny006TaxContribRateValidateQuarter1.xml");
        }

        [Test]
        public void ValidateSaveQuartelyTotalPayrollExpenseSecondQuarterTaxCRate()
        {
            Database.Macros.BusinessRules.EnableRetroCalcs();
            SaveNy006Record(CurrentYear, "04/01", Between375And437);
            ValidateTaxCRate("Ny006TaxContribRateValidateQuarter2.xml");
            Database.Macros.BusinessRules.DisableRetroCalcs();
        }

        [Test]
        public void ValidateSaveQuartelyTotalPayrollExpenseThirdQuarterTaxCRate()
        {
            SaveNy006Record(NextYear, "07/01", Between312And375);
            ValidateTaxCRate("Ny006TaxContribRateValidateQuarter3.xml");
        }

        [Test]
        public void ValidateSaveQuartelyTotalPayrollExpenseFourthQuarterTaxCRate()
        {
            SaveNy006Record(CurrentYear, "10/01", Over437500);
            ValidateTaxCRate("Ny006TaxContribRateValidateQuarter4.xml");
        }

        #endregion

        #region W-2 Box 14 Label Tests

        [Test]
        public void TestW2Box14Save()
        {
            SaveNy006Record(CurrentYear, "07/01", Between312And375);
            UltiPro.Macros.BusinessRules.NavigateToTaxContribPage("NY006");

            // Set Employer ID number and W-2 Box 14 Label
            Page.Set(page => page.EmployerIdNumberTextBox, "84567");
            Page.Set(page => page.W2Box14DropDown, "D125");
            SaveNy006Record(CurrentYear, "07/01", Under312500);
            UltiPro.Macros.BusinessRules.NavigateToTaxContribPage("NY006");

            AssertRowsExist(
                new[] { "0.00 %", string.Format("7/01/{0}", CurrentYear), Under312500 },
                new[] { "0.34 %", string.Format("04/01/{0}", CurrentYear), Over437500 });

            ValidateTaxCRate("Ny006TaxContribRateValidateW2Box14Save.xml");

            Database.Company.RollBackDatabase();
        }

        [Test]
        public void TestW2Box14SaveWithoutUpdateContributionRateChecked()
        {
            Page.Set(page => page.EmployerIdNumberTextBox, "Ab745");
            Page.Set(page => page.W2Box14DropDown, "408CU");
            Page.ButtonBar.Click(bar => bar.Save);

            UltiPro.Macros.BusinessRules.NavigateToTaxContribPage("NY006");
            Page.Is(page => page.EmployerIdNumberTextBox, "value", "Ab745");
            Page.Is(page => page.W2Box14DropDown, "value", "408CU");
            Page.NotSelected(page => page.UpdateContributionRateCheckbox);
        }

        #endregion

        #region RetroCalc Option Tests

        [Test]
        public void TestSaveWithCompOptionOn()
        {
            Database.Macros.BusinessRules.EnableRetroCalcs();
            SaveNy006Record(CurrentYear, "04/01", Between312And375);
            UltiPro.Macros.BusinessRules.NavigateToTaxContribPage("NY006");
            AssertRowsExist(new[] { "0.11 %", string.Format("4/01/{0}", CurrentYear), Between312And375 });
            Database.Macros.BusinessRules.DisableRetroCalcs();
        }

        [Test]
        public void TestSaveWithCompOptionOffAndTaxFilingThrowsError()
        {
            Database.Macros.BusinessRules.DisableRetroCalcs();
            SaveNy006Record(CurrentYear, "04/01", Between312And375);
            Page.ErrorMessages.Has(RetroErrorMessage);
        }

        #endregion

        #region Helpers

        private void ValidateTaxCRate(string validationXml)
        {
            var sql = new StringBuilder();
            sql.Append("Select TcrContributionRate,TcrEffectiveDate,TcrEffectiveStopDate,TcrHasBeenReplaced ");
            sql.Append("from TaxCRate ");
            sql.AppendFormat("Where TcrTaxCode = 'NY006' and TcrCoid = '{0}' ", Coid);
            sql.Append("Order by TcrEffectiveDate, TcrHasBeenReplaced");
            Database.Company.Verify(sql.ToString(), validationXml);
        }

        private string[] GetValidYears()
        {
            return CurrentDate.Year == 2012 ? new[] { "2012", "2013" } : new[] { PriorYear, CurrentYear, NextYear };
        }

        private void ValidateAvailableQuarters()
        {
            // Assert prior year available quarters unless year is 2012
            if (CurrentYear != "2012")
            {
                Page.Set(page => page.NY006YearDropDown, PriorYear);
                Page.HasOptions(page => page.NY006QuarterDropDown, SelectOption.Text, "1", "2", "3", "4");

                Page.Set(page => page.NY006YearDropDown, CurrentYear);
                Page.HasOptions(page => page.NY006QuarterDropDown, SelectOption.Text, "1", "2", "3", "4");
            }
            else
            {
                Page.Set(page => page.NY006YearDropDown, CurrentYear);
                Page.HasOptions(page => page.NY006QuarterDropDown, SelectOption.Text, "2", "3", "4");
            }

            Page.Set(page => page.NY006YearDropDown, NextYear);
            Page.HasOptions(page => page.NY006QuarterDropDown, SelectOption.Text, "1", "2", "3", "4");
        }

        private void ValidateQuarterlyPayrollExpense()
        {
            Page.Set(page => page.NY006YearDropDown, NextYear);
            Page.HasOptions(
                page => page.NY006QuarterlyTotalPayrollExpenseDropDown,
                SelectOption.Text,
                Under312500,
                Between312And375,
                Between375And437,
                Over437500);
        }

        private void SaveNy006Record(string year, string quarter, string description)
        {
            Page.Click(page => page.UpdateContributionRateCheckbox);
            Page.Set(page => page.NY006YearDropDown, year);
            Page.Set(page => page.NY006QuarterDropDown, quarter);
            Page.Set(page => page.NY006QuarterlyTotalPayrollExpenseDropDown, description, SelectOption.Text);
            Page.ButtonBar.Click(bar => bar.Save);
        }

        private void AssertRowsExist(params string[][] rowContent)
        {
            foreach (var row in rowContent)
            {
                //Page.NY006HistoryGrid.Row(row).RowExists();
                Page.NY006HistoryGrid.Row(grid => grid.Rate, row[0], 
                                          grid => grid.EffectiveDate, row[1], 
                                          grid => grid.Description, row[2]).RowExists();
            }

            //Page.NY006HistoryGrid.Row(rowContent.Length).RowNotExists();
        }

        #endregion
    }
}
